package srvbiz

import (
	"cloud_worm/util/unet/usocket"
	"cloud_worm/access/server/client"
	"strings"
	"fmt"
	"cloud_worm/util/proto/ujson"
	"time"
	"github.com/golang/glog"
)

type ServiceManage struct {

}

func (s *ServiceManage) Handler(conn usocket.Connection) {
	agent, err := s.accept(conn)
	if err != nil {
		glog.Warningf("handler connect error: %s", err.Error())
		return
	}

	for {
		data, err := agent.Connection.Read()
		if err != nil {
			glog.Warningf("client '%s' socket read error: %s", agent.IP, err.Error())
			client.AgentPoolInst.DelAgent(agent)
			break
		}

		var recvMsg ujson.ProtoMsg
		if err := recvMsg.UnmarshalJSON(data); err != nil {
			glog.Errorf("socket receive data, Unmarshal error: %s", err.Error())
			continue
		}

		switch recvMsg.Type {
		case ujson.ProtoId:
			msg := &MsgWormId{}
			msg.Deal(agent, recvMsg.Content)

		case ujson.ProtoVersion:
			msg := &MsgVersion{}
			msg.Deal(agent, recvMsg.Content)

		case ujson.ProtoCmdMsg:
			msg := &MsgCmd{}
			msg.Deal(agent, recvMsg.Content)

		case ujson.ProtoWpMsgResp:
			msg := &MsgWeaponResp{}
			msg.Deal(agent, recvMsg.Content)

		case ujson.ProtoHeartBeat:
			agent.Timestamp = time.Now().Unix()
			agent.Connection.Write(data)

		case ujson.ProtoMsgPush:
			msg := &MsgPush{}
			msg.Deal(agent, recvMsg.Content)

		default:
			glog.Errorf("'%s' unknown msg type'%d' input.", agent.IP, recvMsg.Type)
		}
	}

	return
}

func (s *ServiceManage) accept(conn usocket.Connection) (*client.Agent, error) {
	var cliIP string
	if tmps := strings.Split(conn.Conn.RemoteAddr().String(), ":"); len(tmps) >= 1 {
		cliIP = tmps[0]
	}
	if cliIP == "" {
		return nil, fmt.Errorf("parser agent ip eror")
	}

	if client.AgentPoolInst.HaveConnByIP(cliIP) {
		msg := ujson.ProtoMsg{
			Type: ujson.ProtoConnDuplicate,
		}
		buf, err := msg.MarshalJSON()
		if err != nil {
			return nil, err
		}
		conn.Write(buf)

		conn.Conn.Close()
		return nil, fmt.Errorf("client '%s' is duplicate", cliIP)
	}

	// 新增一个connection
	newAgent := client.AgentPoolInst.AgentFree.Get().(*client.Agent)
	newAgent.IP = cliIP
	newAgent.Timestamp = time.Now().Unix()
	newAgent.Connection = conn
	client.AgentPoolInst.NewConnByIP(newAgent)

	return newAgent, nil
}